package com.emergency.embackend.service.impl;

import com.emergency.embackend.common.PageParams;
import com.emergency.embackend.entity.HelpComment;
import com.emergency.embackend.entity.HelpData;
import com.emergency.embackend.entity.HelpHot;
import com.emergency.embackend.exception.EmException;
import com.emergency.embackend.mapper.HelpDataMapper;
import com.emergency.embackend.service.DataViewService;
import com.emergency.embackend.service.HelpDataService;
import com.emergency.embackend.service.OperateService;
import com.emergency.embackend.utils.RedisConstants;
import com.emergency.embackend.utils.UserHolder;
import com.emergency.embackend.vo.HelpDetailVo;
import com.emergency.embackend.vo.HelpOneVo;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

@Service
public class HelpDataServiceImpl implements HelpDataService {
    @Autowired
    private HelpDataMapper helpDataMapper;
    @Autowired
    private OperateService operateService;

    @Autowired
    private DataViewService dataViewService;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    private BlockingQueue<HelpData> helpDataTasks = new ArrayBlockingQueue<>(1024 * 1024);

    //添加求助信息
    @Override
    public void add(HelpData helpData, Long userId) {
        //添加帮助信息
        helpDataMapper.add(helpData, userId);
    }
    //删除求助信息
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(String helpId) {
        Long userId=UserHolder.getUser().getId();
        helpDataMapper.delete(helpId,userId);
        stringRedisTemplate.delete(RedisConstants.VIEW_HELP_COUNT_KEY+helpId);
        stringRedisTemplate.delete(RedisConstants.VIEW_HELP_REPEAT_KEY+helpId);
    }
    //修改求助信息
    @Override
    public void update(HelpData helpData) {
        helpDataMapper.update(helpData);
    }
    //获取用户自己求助信息
    @Override
    public PageInfo pageByUser(PageParams pageParams, Long userId) {
        PageHelper.startPage(pageParams.getPageNum(), pageParams.getPageSize());
        List<HelpOneVo> resList = helpDataMapper.pageByUser(userId);
        resList.forEach(e -> {
            if(e.getView()!=null) {
                e.setView(dataViewService.getViewCount(RedisConstants.VIEW_HELP_COUNT_KEY + e.getHelpId()) + e.getView());
            }else{
                e.setView(dataViewService.getViewCount(RedisConstants.VIEW_HELP_COUNT_KEY + e.getHelpId()));
            }
        });
        PageInfo pageInfo = new PageInfo(resList);
        return pageInfo;
    }

    @Override
    public PageInfo pageAll(PageParams pageParams) {
        PageHelper.startPage(pageParams.getPageNum(), pageParams.getPageSize());
        List<HelpOneVo> resList = helpDataMapper.pageAll();
        resList.forEach(e -> {
            if(e.getView()!=null) {
                e.setView(dataViewService.getViewCount(RedisConstants.VIEW_HELP_COUNT_KEY + e.getHelpId()) + e.getView());
            }else{
                e.setView(dataViewService.getViewCount(RedisConstants.VIEW_HELP_COUNT_KEY + e.getHelpId()));
            }
        });
        PageInfo pageInfo = new PageInfo(resList);
        return pageInfo;
    }
    //获取某一个求助信息
    @Override
    public HelpDetailVo getOne(Long helpId) {
        HelpDetailVo data = helpDataMapper.getOne(helpId);
        if (data == null) {
            throw new EmException("401", "内容丢失，请咨询管理员");
        }
        HelpDetailVo detailVo=new HelpDetailVo();
        BeanUtils.copyProperties(data,detailVo);
        //浏览量添加
        if (UserHolder.getUser() != null) {
            operateService.addViews(helpId, UserHolder.getUser().getId(), '3');
        } else {
            operateService.addViews(helpId, null, '3');
        }
            data.setView(dataViewService.getViewCount(RedisConstants.VIEW_HELP_COUNT_KEY + data.getHelpId()) + data.getView());
        detailVo.setHelpComments(getCommentByHelpId(helpId));
        return detailVo;
    }
    private List<HelpComment> getCommentByHelpId(Long helpId){
        List<HelpComment> commentList=helpDataMapper.getComment(helpId);
        List<HelpComment> rootList=new ArrayList<>();
        Long rootId = 0L;
        //获取根节点数据
        commentList.forEach(e->{
            if(rootId.equals(e.getRootId())){
                e.setHelpComments(new ArrayList<>());
                rootList.add(e);
            }
        });
        //遍历根节点并且构造数据
        rootList.forEach(root->{
            root.getHelpComments().add(findChildComment(commentList,root));
        });
        return rootList;
    }
    private HelpComment findChildComment(List<HelpComment> commentList, HelpComment father) {
        //初始化当前的list
       father.setHelpComments(new ArrayList<>());
       commentList.forEach(e->{
           if(e.getRootId().equals(father.getHelpCommentId())){
               father.getHelpComments().add(findChildComment(commentList,e));
           }
       });
       return father;
    }
    //添加评论
    @Override
    public void addComment(HelpComment helpComment) {
        helpDataMapper.addComment(helpComment);
    }

    @Override
    public void updateHot(Long helpId) {
        int hot=helpDataMapper.getHot(helpId)+1;
        helpDataMapper.updateHot(hot,helpId);
    }
    private OperateService proxy;
    @Override
    public Integer like(Long id, char type) {
        String hotKey = null;
        String hotCountKey = null;
        //redis储存键值
        hotKey = RedisConstants.VIEW_HELP_COUNT_KEY + id;
        hotCountKey = RedisConstants.VIEW_HELP_COUNT_KEY + id;

        //获取id
        Long userId = UserHolder.getUser().getId();
        Boolean isLike = stringRedisTemplate.opsForSet().isMember(hotKey, String.valueOf(userId));
        //获取点赞数
        String s = stringRedisTemplate.opsForValue().get(hotCountKey);
        Integer likeCount = null;
        //生成对象
        HelpData helpData = createLikeOperate(id, userId);
        //已经点赞
        proxy = (OperateService) AopContext.currentProxy();
        if (isLike) {
            likeCount = Integer.valueOf(s);
            //总的点赞数-1
            stringRedisTemplate.opsForValue().set(hotCountKey, String.valueOf(likeCount - 1));
            //挪出set列表
            stringRedisTemplate.opsForSet().remove(hotKey, String.valueOf(userId));
            helpData.setHot(String.valueOf(0));
            helpDataTasks.add(helpData);
            //返回0表示 要取消点赞
            return Integer.valueOf(0);
        }
        //没有点赞
        //总的点赞数+1
        if(s!=null) {
            likeCount = Integer.valueOf(s);
            stringRedisTemplate.opsForValue().set(hotCountKey, String.valueOf(likeCount + 1));
        }else{
            stringRedisTemplate.opsForValue().set(hotCountKey,"1");
        }
        //加入set列表
        stringRedisTemplate.opsForSet().add(hotKey, String.valueOf(userId));
        helpData.setHot(String.valueOf(1));
        //返回1表示点赞成功
        //异步执行对于数据库的操作
        helpDataTasks.add(helpData);
        return Integer.valueOf(1);
    }

    @Override
    public PageInfo hotByUptime(PageParams pageParams) {
        PageHelper.startPage(pageParams.getPageNum(), pageParams.getPageSize());
        List<HelpOneVo> resList = helpDataMapper.hotByUptime();
        resList.forEach(e -> {
            if(e.getView()!=null) {
                e.setView(dataViewService.getViewCount(RedisConstants.VIEW_HELP_COUNT_KEY + e.getHelpId()) + e.getView());
            }else{
                e.setView(dataViewService.getViewCount(RedisConstants.VIEW_HELP_COUNT_KEY + e.getHelpId()));
            }
        });
        PageInfo pageInfo = new PageInfo(resList);
        return pageInfo;
    }

    @Override
    public int changeHot(Long helpId) {
        int hot=  helpDataMapper.getHot(helpId)+1;
        helpDataMapper.changeHot(hot, helpId);
        return helpDataMapper.getHot(helpId);
    }


    private HelpData createLikeOperate(Long id, Long userId) {
        HelpData helpData = new HelpData();
        helpData.setHelpId(id);
        helpData.setUserId(userId);
        return helpData;
    }
}
